package com.ly.gateway.fifter;

import com.common.core.constant.HttpStatus;
import com.ly.gateway.base.GateWayResponse;
import com.ly.gateway.config.properties.CurrentLimitingAddress;
import com.ly.gateway.config.properties.IgnoreWhiteProperties;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RRateLimiter;
import org.redisson.api.RateIntervalUnit;
import org.redisson.api.RateType;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.core.Ordered;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.List;

@Component
@Slf4j
public class CounterLimitFilter extends AbstractGatewayFilter implements Ordered {

    @Autowired
    private RedissonClient redissonClient;

    @Autowired
    private CurrentLimitingAddress currentLimitingAddress;

    @Autowired
    private GateWayResponse gateWayResponse;


    @Override
    boolean should(ServerWebExchange exchange) {
        //随便写个开关
        List<String> limitings = currentLimitingAddress.getLimitings();
        String requestPath = exchange.getRequest().getPath().value();
        return limitings.contains(requestPath);
    }

    //接口限流
    //todo ip限流
    //todo 用户id限流
    @Override
    Mono<Void> doFilter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //初始化个令牌桶 每个接口一个令牌通(可以有很多接口 也可以自定义些限流接口)

        //每秒恒定速率向桶里面放令牌

        //发过来一个请求从桶里面拿一个令牌

        //桶内的令牌被拿没了 拦住请求

        String requestPath = exchange.getRequest().getPath().value();
        //todo 可以加个判断判定指定某几个接口进行限流

        String limitKey = "rate_limit:" + requestPath;

        //为每个接口初始化令牌桶
        RRateLimiter limiter = redissonClient.getRateLimiter(limitKey);

        /**并为每个接口设置了限流速率为每秒最多 10 个请求
        limiter.trySetRate(RateType.OVERALL, 多少个请求, 秒, RateIntervalUnit.SECONDS);
        现在是每秒一个请求 能实验出来 好不好使 得根据业务来具体配置 每秒多少个请求合适
         注:如果更改了速率问题 一定要删除掉原来写在redis 里面的值 rate_limit:开头的 否则修改完也不好使
         */
        limiter.trySetRate(RateType.OVERALL, 2, 1, RateIntervalUnit.SECONDS);

        //并使用该键获取或创建令牌桶。
        // 然后，我们尝试从令牌桶中获取令牌，如果获取成功，则继续执行后续过滤器链；否则，返回一个限流响应。
        if (limiter.tryAcquire()) {
            return chain.filter(exchange);
        } else {
            return gateWayResponse.setUnauthorizedResponse(exchange,"系统繁忙");
        }
    }



    @Override
    public int getOrder() {
        return 1;
    }




}
